home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / MacSource / TextEditor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-07  |  36.1 KB  |  1,409 lines  |  [TEXT/CWIE]

  1. /*==============================================================================
  2. Project:    POV-Ray
  3.  
  4. Version:    3
  5.  
  6. File:    TextEditor.c
  7.  
  8. Description:
  9.     This file contains Macintosh-specific routines for the
  10.     source code text editor.
  11. ------------------------------------------------------------------------------
  12. Author:
  13.     Symantec, mods by Jim Nitchals, more mods & Think 6 updates by Eduard [esp] Schwan
  14. ------------------------------------------------------------------------------
  15.     from Persistence of Vision(tm) Ray Tracer
  16.     Copyright 1996 Persistence of Vision Team
  17. ------------------------------------------------------------------------------
  18.     NOTICE: This source code file is provided so that users may experiment
  19.     with enhancements to POV-Ray and to port the software to platforms other 
  20.     than those supported by the POV-Ray Team.  There are strict rules under
  21.     which you are permitted to use this file.  The rules are in the file
  22.     named POVLEGAL.DOC which should be distributed with this file. If 
  23.     POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  24.     Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  25.     Forum.  The latest version of POV-Ray may be found there as well.
  26.  
  27.     This program is based on the popular DKB raytracer version 2.12.
  28.     DKBTrace was originally written by David K. Buck.
  29.     DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  30. ------------------------------------------------------------------------------
  31. Change History:
  32.     920815    [jln]    version 1.0 Mac released.
  33.     920908    [esp]    version 1.1 alpha Mac
  34.     920912    [esp]    changed window id to 1000 & moved #define here from POVMac.h
  35.     921110    [esp]    Added TextEditor.h file & pulled in defs to there
  36.     921207    [esp]    Added code to handle zoom box
  37.     921211    [esp]    Fixed bug in Open: if open failed, left New & Open items dimmed
  38.     930710    [esp]    fixed "cancelling of save-as dialog" logic
  39.     930817    [esp]    Added FlushVol calls in SaveFile and SaveAs to force disk update
  40.     931001    [esp]    version 2.0 finished (Released on 10/4/93)
  41.     931119    [djh]    2.0.1 conditionally compiles for PPC machines, keyword __powerc
  42.     940416    [PFS]    2.2.1 greatly reworked to clean up PPC support and provide CodeWarrior projects
  43.     960422    [esp]    3.0b6 Major rework to use TE32K code for >32K text files
  44.     960620    [esp]    3.0b7 Added code to convert Unix LF-only files to Mac CR-only files.
  45.     960621    [esp]    3.0b7 Added simple Match Brace function.
  46.     960714    [esp]    3.0F1 Added real Revert dialog instead of reusing save dialog!
  47. ==============================================================================*/
  48.  
  49.  
  50. #include "TextEditor.h"
  51.  
  52. /*==== Standard C headers ====*/
  53. #include <stdio.h>
  54.  
  55. /*==== Mac toolbox headers ====*/
  56.  
  57. #include <types.h>        // basic types
  58. #include <errors.h>        // noErr, etc.
  59. #include <files.h>        // FSOpen, etc.
  60. #include <fonts.h>        // monaco, etc.
  61. #include <memory.h>        // NewHandle, etc.
  62. #include <menus.h>        // MenuHandle, etc.
  63. #include <packages.h>    // SFGetFile, etc.
  64. #include <scrap.h>        // ZeroScrap, etc.
  65. #include <toolutils.h>    // watchCursor, etc.
  66. #include <windows.h>    // SizeWindow, etc.
  67. #include <processes.h>    // ExitToShell
  68.  
  69.  
  70. /*==== POV Mac Library routines =====*/
  71.  
  72. #include "PovMac.h"        // fmn_open
  73. #include "UtilLib.h"
  74. #include "ImageWindow.h" // CloseImageWindow(), gImageWindIsValid
  75. #include "FilePrefs.h"
  76. #include "TE32K.h"        // TE32K support
  77. #include "UndoRedoSystem.h"
  78.  
  79. /*==== globals (external scope) ====*/
  80.  
  81. WindowPtr            gSrcWind_Window;
  82. Boolean                gSrcWind_dirty;
  83. Boolean                gSrcWind_visible;
  84. Str255                 gSrcWind_FileName;
  85. short                gSrcWind_VRefNum;
  86. TE32KHandle            gSrcWind_TE32KH;
  87.  
  88.  
  89. /*==== globals (local scope) ====*/
  90.  
  91. static    WindowRecord        gWindowRecord;
  92. static    int                    gLineCount;
  93. static    Cursor                gEditCursor;
  94. static    ControlActionUPP    vScrollUPP = NULL;
  95. static    ControlHandle         gSrcWind_VScroll;
  96.  
  97. // this should be moved to a user preference when I have time!
  98. #define TAB_WIDTH            4
  99. #define    EDITOR_TEXTFONT        monaco
  100. #define    EDITOR_TEXTSIZE        9
  101.  
  102.  
  103. // ==============================================
  104. static pascal void ScrollProc(ControlHandle theControl, short theCode);
  105. static void SrcWindClickLoop(void);
  106. static void SrcWindClickRoutine(void);
  107.  
  108. // ==============================================
  109. #define SrcWind_WindID     1000
  110. #define ErrorAlert        256
  111. #define    SaveAlertID        257
  112. #define    RevertAlertID    258
  113.  
  114. #define aaSave            1
  115. #define aaDiscard        2
  116. #define aaCancel        3
  117.  
  118. #define SBarWidth        15
  119.  
  120. #define    ours(w)        ((gSrcWind_Window != NULL) && (w == gSrcWind_Window))
  121.  
  122. #define    kUntitledFName    "\pUntitled.POV"
  123.  
  124.  
  125. // ==============================================
  126. int SetUpFiles(void)
  127. {
  128.     pStrCopy(kUntitledFName, gSrcWind_FileName);
  129.     gSrcWind_VRefNum = 0;
  130.     gSrcWind_dirty = 0;
  131.     return 0; // should be void fn!?
  132. }
  133.  
  134.  
  135.  
  136. // ==============================================
  137. int DoFile(int item)
  138. {
  139.     short     vRef, refNum;
  140.     Str255    fn;
  141.  
  142.     switch (item) {
  143.  
  144.         case fmn_open:
  145.             HideWindow(gSrcWind_Window);    /* gives a sense of closing the old file. */
  146.             if (OldFile(fn, &vRef))
  147.             {
  148.                 gSrcWind_VRefNum = 0;
  149.                 gSrcWind_dirty = false; // may turn ON in ReadFile
  150.                 if (FSOpen(fn, vRef, &refNum)==noErr) {
  151.                     if (ReadFile(refNum)==noErr) {
  152.                         pStrCopy(fn, gSrcWind_FileName);
  153.                         gSrcWind_VRefNum = vRef;
  154.                         SetWTitle(gSrcWind_Window, gSrcWind_FileName);
  155.                     }
  156.                     if (FSClose(refNum)==noErr) ;
  157.                     ShowWindow(gSrcWind_Window);
  158.                     gSrcWind_visible = true;
  159.                     TE32KSetSelect(0, 0, gSrcWind_TE32KH);
  160.                     ShowSelect();
  161.  
  162.                     Init_UndoRedoSystem();
  163.                 }
  164.                 else
  165.                     FileError("\pError opening ", fn);
  166.             }
  167.             break;
  168.  
  169.         case fmn_close:
  170.             if (gSrcWind_dirty)
  171.             {
  172.                 int    notClosed=0;
  173.                 ParamText("\pSave changes to \"", gSrcWind_FileName, "\p\"?", "\p");
  174.                 ShowArrowCursor();
  175.                 switch (Alert(SaveAlertID, 0L))
  176.                 {
  177.                 case aaSave:
  178.                     if (gSrcWind_VRefNum == 0)
  179.                     { // create new file
  180.                         pStrCopy(gSrcWind_FileName, fn);
  181.                         if (!SaveAs(fn, &vRef))
  182.                             notClosed=1;
  183.                     }
  184.                      else // save existing file
  185.                         if (!SaveFile(gSrcWind_FileName, gSrcWind_VRefNum))
  186.                             notClosed=1;
  187.                      break;
  188.                  case aaCancel:
  189.                     notClosed=1;
  190.                     break;
  191.                  case aaDiscard:
  192.                     gSrcWind_dirty = 0;
  193.                     break;
  194.                  }
  195.                 if (notClosed)
  196.                     return 0; // error, just return
  197.              } // if dirty
  198.  
  199.             Dispose_UndoRedoSystem();
  200.  
  201.             CloseMyWindow();
  202.             break;
  203.  
  204.         case fmn_save:
  205.             // if file already open
  206.             if (gSrcWind_VRefNum != 0)
  207.             {
  208.                 if (!SaveFile(gSrcWind_FileName, gSrcWind_VRefNum))
  209.                     return(0);
  210.                 break;
  211.             }
  212.             // else drop through to here..
  213.  
  214.         case fmn_saveas:
  215.             pStrCopy(gSrcWind_FileName, fn);
  216.             if (SaveAs(fn, &vRef))
  217.             {
  218.                 pStrCopy(fn, gSrcWind_FileName);
  219.                 gSrcWind_VRefNum = vRef;
  220.                 SetWTitle(gSrcWind_Window, gSrcWind_FileName);
  221.             }
  222.             else
  223.                 return(0);
  224.             break;
  225.  
  226.         case fmn_revert:
  227.             ParamText("\pRevert to last saved version of \"", gSrcWind_FileName, "\p\"?", "\p");
  228.             ShowArrowCursor();
  229.             switch (Alert(RevertAlertID, 0L)) {
  230.             case aaSave:
  231.                 // delete existing text
  232.                 SelectAllText();
  233.                 SrcWindClearSel();
  234.                 // read file back in
  235.                 if ((gSrcWind_VRefNum != 0) &&
  236.                     (FSOpen(gSrcWind_FileName, gSrcWind_VRefNum, &refNum)==noErr))
  237.                     {
  238.                     gSrcWind_dirty = false; // may turn ON in ReadFile
  239.                     ReadFile(refNum); 
  240.                     if (FSClose(refNum)==noErr) ;
  241.                     }
  242.                 ShowWindow(gSrcWind_Window);
  243.                 gSrcWind_visible = true;
  244.                 UpdateWindow(gSrcWind_Window);
  245.              case aaCancel:
  246.              case aaDiscard:
  247.                 return(0);
  248.              }
  249.     
  250.             break;
  251.  
  252.         case fmn_quit:
  253.             Dispose_UndoRedoSystem();
  254.             if (DoFile(fmn_close))
  255.                 ExitToShell();
  256.     }
  257.     return(1);
  258. }
  259.  
  260.  
  261.  
  262. // ==============================================
  263. static Point SFwhere;
  264. static SFReply reply;
  265.  
  266.  
  267. int SaveAs(Str255 fn, short *vRef)
  268. {
  269.     short refNum;
  270.     
  271.     if (NewFile(fn, vRef)) 
  272.         if (!CreateFile(fn, vRef, &refNum))
  273.         {
  274.             FileError("\pError creating file ", fn);
  275.             return (0);
  276.         }
  277.         else
  278.         {
  279.             char hstate;
  280.             
  281.             hstate = HGetState((**gSrcWind_TE32KH).hText);
  282.             HLock((**gSrcWind_TE32KH).hText);
  283.             if (WriteFile(refNum, (*(**gSrcWind_TE32KH).hText), (long)(**gSrcWind_TE32KH).teLength))
  284.             {
  285.                 FileError("\pError writing file ", fn);
  286.                 return (0);
  287.             }
  288.             HSetState((**gSrcWind_TE32KH).hText, hstate);
  289.             FSClose(refNum);
  290.             gSrcWind_dirty = 0;
  291.             // flush any buffers to disk
  292.             FlushVol(NULL, *vRef);
  293.             return(1);
  294.         }
  295.     return (0);
  296. }
  297.  
  298.  
  299.  
  300. // ==============================================
  301. int SaveFile(Str255 fn, short vRef)
  302. {
  303.     short refNum;
  304.     short anError;
  305.  
  306.     anError = FSOpen(fn, vRef, &refNum);
  307.     if (anError != noErr)
  308.     {
  309.         FileError("\pError opening file ", fn);
  310.         return (1);
  311.     }
  312.     else
  313.     {
  314.         char hstate;
  315.         
  316.         hstate = HGetState((**gSrcWind_TE32KH).hText);
  317.         HLock((**gSrcWind_TE32KH).hText);
  318.         anError = WriteFile(refNum, (*(**gSrcWind_TE32KH).hText), (long)(**gSrcWind_TE32KH).teLength);
  319.         if (anError)
  320.             FileError("\pError writing file ", fn);
  321.         HSetState((**gSrcWind_TE32KH).hText, hstate);
  322.         gSrcWind_dirty = 0;
  323.         FSClose(refNum);
  324.         // save prefs out too
  325.         FilePrefs_Write(vRef, fn);                            
  326.         // flush any buffers to disk
  327.         FlushVol(NULL, vRef);
  328.         return(1);
  329.     }
  330. }
  331.  
  332.  
  333.  
  334. // ==============================================
  335. int NewFile(Str255 fn, short *vRef)
  336. {
  337.     ShowArrowCursor();
  338.     GetBestDialogPos(&SFwhere, (WindowPtr)&gp2wWindow);
  339.     SFPutFile(SFwhere, "\pSave POV-Ray text file as", fn, 0L, &reply);
  340.     if (!reply.good)
  341.         return (0);
  342.     else {
  343.         pStrCopy(reply.fName, fn);
  344.         *vRef = reply.vRefNum;
  345.         return(1);
  346.     }
  347. }
  348.  
  349.  
  350.  
  351. // ==============================================
  352. int OldFile(Str255 fn, short *vRef)
  353. {
  354.     SFTypeList    myTypes;
  355.     
  356.     myTypes[0]='TEXT';
  357.  
  358.     ShowArrowCursor();
  359.     GetBestDialogPos(&SFwhere, (WindowPtr)&gp2wWindow);
  360.     SFGetFile(SFwhere, "\p", 0L, 1, myTypes, 0L, &reply );
  361.  
  362.     if (!reply.good)
  363.         return (0);
  364.     else {
  365.         pStrCopy(reply.fName, fn);
  366.         *vRef = reply.vRefNum;
  367.         return(1);
  368.     }
  369. }
  370.  
  371.  
  372.  
  373. // ==============================================
  374. int CreateFile(Str255 fn, short *vRef, short *theRef)
  375. {
  376.     OSErr io;
  377.     
  378.     io=Create(fn, *vRef, kAppSignature, 'TEXT');
  379.     if ((io == noErr) || (io == dupFNErr))
  380.         io = FSOpen(fn, *vRef, theRef );
  381.  
  382.     return ((io == noErr) || (io == dupFNErr));
  383. }
  384.  
  385.  
  386.  
  387. // ==============================================
  388. int WriteFile(short refNum, char *p, long num)
  389. {
  390.     OSErr io;            
  391.     /* gee,    somebody should check the return code for errors */
  392.     io=FSWrite(refNum, &num, p);
  393.     if (io)
  394.         return(io);
  395.     io=SetEOF(refNum, num);
  396.     return(io);
  397. }
  398.  
  399.  
  400.  
  401. // ==============================================
  402. // This routine sweeps through the buffer passed, looking for lone LFs
  403. // (with no CR before them ala MSDOS) and switches the LF in place
  404. // to a CR for the Macintosh.  This allows us to read/convert Unix
  405. // scene files and convert them right to Mac format.
  406. // SIDE EFFECT: Turns on the global DIRTY flag if any LFs are converted,
  407. // forcing user to save the altered file or abort the changes.
  408. #define LF_CHAR        0x0a
  409. #define CR_CHAR        0x0d
  410. static void ConvertUnixBuffer(Boolean * sawCRFlag, char * buffer, long bufferSize)
  411. {
  412.     // loop through entire buffer...
  413.     for ( ; bufferSize; bufferSize--, buffer++)
  414.         {
  415.         // Did we find a line feed?
  416.         if (*buffer == LF_CHAR)
  417.             {
  418.             // if previous char was NOT a CR, it is OK to convert
  419.             if (*sawCRFlag == false)
  420.                 {
  421.                 *buffer = CR_CHAR;        // convert from Unix LF to Mac CR
  422.                 gSrcWind_dirty = true;    // mark ourselves as dirty!
  423.                 }
  424.             *sawCRFlag = false; // nope, it was a line feed!
  425.             }
  426.         // is it a CR?
  427.         else if (*buffer == CR_CHAR)
  428.             {
  429.             *sawCRFlag = false; // Oh oh, remember that we saw this for next time through!
  430.             }
  431.         // it is some other uninteresting character...
  432.         else
  433.             *sawCRFlag = false; // nope, it was something else!
  434.         }
  435. }
  436.  
  437. // ==============================================
  438. #define READ_BUF_SIZE    1024L*10L    // how many KBytes to read at a time from file
  439. int ReadFile(short refNum)
  440. {
  441.     OSErr    io = noErr;
  442.     long    totalBytes, count;
  443.     Ptr        buffer;
  444.     Boolean    crFlag=false;
  445.  
  446.     // allocate temp buffer to read into
  447.     buffer = NewPtr(READ_BUF_SIZE);
  448.     if (buffer == NULL)
  449.         return -108; // out of mem
  450.  
  451.     // get rid of any previous TE stuff
  452.     (**gSrcWind_TE32KH).selStart = 0;
  453.     (**gSrcWind_TE32KH).selEnd = (**gSrcWind_TE32KH).teLength;
  454.     TE32KDelete(gSrcWind_TE32KH);
  455.     // how many total bytes in file?
  456.     GetEOF(refNum, &totalBytes);
  457.     // will we run out of memory?
  458.     if (totalBytes > FreeMem()*2L)
  459.         return -108; // out of mem
  460.     // read the file, "READ_BUF_SIZE" bytes at a time
  461.     do {
  462.         // how much to read this pass?
  463.         count = (totalBytes >= READ_BUF_SIZE) ? READ_BUF_SIZE : totalBytes;
  464.         // read it
  465.         if (count > 0L)
  466.             io = FSRead(refNum, &count, buffer);
  467.         // Convert the buffer from Unix if need be
  468.         ConvertUnixBuffer(&crFlag, buffer, count);
  469.         // stick chars into TE buffer
  470.         if (count > 0L)
  471.             TE32KInsert(buffer, count, gSrcWind_TE32KH);
  472.         // calculate how much is left to read
  473.         totalBytes -= count;
  474.     } while ((io==noErr) && (totalBytes > 0L));
  475.     // done with temp buffer
  476.     DisposePtr(buffer);
  477.  
  478.     return (io);
  479. }
  480.  
  481.  
  482.  
  483. // ==============================================
  484. /* copies a pascal string from p1 to p2 */
  485. int pStrCopy(StringPtr p1, StringPtr p2)
  486. {
  487.     register int len = *p1;
  488.     
  489.     *(p2++) = *(p1++);
  490.     while (--len>=0)
  491.         *(p2++)=*(p1++);
  492.     return 0; // should be void fn!?
  493. }
  494.  
  495.  
  496.  
  497. // ==============================================
  498. int FileError(Str255 s, Str255 f)
  499. {
  500.     ParamText(s, f,"\p", "\p");
  501.     Alert(ErrorAlert, 0L);
  502.     return 0; // should be void fn!?
  503. }
  504.  
  505.  
  506.  
  507. // ==============================================
  508. void PreInitWindows(void)
  509. {
  510.     if (gSrcWind_Window == 0)
  511.     {
  512.         SetUpWindows();
  513.         HideWindow(gSrcWind_Window);    /* just in case it's already visible */
  514.     }
  515. }
  516.  
  517.  
  518. // ==============================================
  519. int SetUpWindows(void)
  520. {
  521.     Rect        viewRect;
  522.     Rect        vScrollRect;
  523.     LongRect    LviewRect;
  524.  
  525.     gSrcWind_Window = GetNewWindow(SrcWind_WindID, &gWindowRecord, (WindowPtr)NULL);
  526.     if (!gSrcWind_Window)
  527.         return 1;
  528.  
  529.     // set the editor's font & size
  530.     SetPort(gSrcWind_Window);
  531.     TextFont(EDITOR_TEXTFONT);
  532.     TextSize(EDITOR_TEXTSIZE);
  533.  
  534.     vScrollRect = (*gSrcWind_Window).portRect;
  535.     vScrollRect.left = vScrollRect.right-SBarWidth;
  536.     vScrollRect.right += 1;
  537.     vScrollRect.bottom -= SBarWidth-1;
  538.     vScrollRect.top -= 1;
  539.     gSrcWind_VScroll = NewControl( gSrcWind_Window, &vScrollRect,
  540.         "\pSrcVScroll", 1, 0, 0, 0, scrollBarProc, 0L);
  541.  
  542.     viewRect = qd.thePort->portRect;
  543.     viewRect.right -= SBarWidth;
  544.     viewRect.bottom -= SBarWidth;
  545.     InsetRect(&viewRect, 2, 2);
  546.     RectToLongRect(&viewRect, &LviewRect);
  547.     gSrcWind_TE32KH = TE32KNew(&LviewRect, &LviewRect);
  548.     if (gSrcWind_TE32KH)
  549.     {
  550.         // Set up the tab width
  551.         (**gSrcWind_TE32KH).tabChars = TAB_WIDTH;
  552.         TE32KSetFontStuff(EDITOR_TEXTFONT, 0, 0, EDITOR_TEXTSIZE, gSrcWind_TE32KH);
  553.  
  554.         TE32KDeactivate(gSrcWind_TE32KH);
  555.         // turn on autoscrolling
  556. // Not this way...
  557. //        (void)TE32KFeatureFlag(teFAutoScr, teBitSet, gSrcWind_TE32KH);
  558. //        TE32KAutoView(TRUE, gSrcWind_TE32KH);
  559. // this way!
  560.         (**gSrcWind_TE32KH).clikLoop = (TE32KProcPtr) SrcWindClickLoop;
  561.  
  562.         // turn on outline hilighting (not working??? [esp])
  563.         (void)TE32KFeatureFlag(teFOutlineHilite, teBitSet, gSrcWind_TE32KH);
  564.     }
  565.     SetView((WindowPtr) qd.thePort);
  566.  
  567.     if (gSrcWind_VScroll)
  568.         HideControl(gSrcWind_VScroll);
  569.  
  570.     gSrcWind_dirty = 0;
  571.  
  572.     Init_UndoRedoSystem();
  573.  
  574.     return 0; // should be void fn!?
  575. }
  576.  
  577.  
  578. // ==============================================
  579. /*
  580. From the TE32K readme:
  581. Warning #2: since TE32K supports editing of such large text files, the text rectangle (destRect)
  582. can easily by taller than 32767 pixels.  “So what?” you ask?  Well, this means that you had
  583. better not be using the value ((**theTEH32K).viewRect.top - (**theTEH32K).destRect.top)
  584. for the setting in your vertical scroll control.  If you do, then you will likely end up setting
  585. the control value to something much larger than its maximum of 32767.  Instead, you would be wise
  586. to set the control's value to
  587.   ((**theTEH32K).viewRect.top - (**theTEH32K).destRect.top) / (**theTEH32K).lineHeight,
  588. which means that now your control keeps track of the top line number, rather than the pixel
  589. distance between the top of the destRect and viewRect.
  590. */
  591. static int AdjustScrollBar(void)
  592. {
  593.     short    ctlVal,screenLines,numLines,oldVal;
  594.  
  595.     ctlVal = ((**gSrcWind_TE32KH).viewRect.top - (**gSrcWind_TE32KH).destRect.top)/(**gSrcWind_TE32KH).lineHeight;
  596.     screenLines = ((**gSrcWind_TE32KH).viewRect.bottom - (**gSrcWind_TE32KH).viewRect.top)/(**gSrcWind_TE32KH).lineHeight;
  597.     numLines = (**gSrcWind_TE32KH).nLines;
  598.     
  599.     if (ctlVal > numLines-screenLines)
  600.         SetControlMaximum(gSrcWind_VScroll, ctlVal);
  601.     else
  602.         SetControlMaximum(gSrcWind_VScroll, (numLines-screenLines > 0) ? numLines-screenLines : 0);
  603.     
  604.     oldVal = GetControlValue(gSrcWind_VScroll);
  605.     
  606.     if (oldVal != ctlVal)
  607.         SetControlValue(gSrcWind_VScroll, ctlVal);
  608.  
  609. //    ShowControl(gSrcWind_VScroll);
  610.     return 0; // should be void fn!?
  611. }
  612.  
  613.  
  614.  
  615. // ==============================================
  616. int ShowSelect(void)
  617. {
  618.     int        topLine, bottomLine, theLine, scrollAmt;
  619.     
  620.     AdjustScrollBar();
  621.     
  622.     // what lines are shown...
  623.     topLine = GetControlValue(gSrcWind_VScroll);
  624.     bottomLine = topLine + gLineCount;
  625.     // if selection is off the screen...
  626.     if ((**gSrcWind_TE32KH).selStart < (**gSrcWind_TE32KH).lineStarts[topLine] ||
  627.             (**gSrcWind_TE32KH).selStart >= (**gSrcWind_TE32KH).lineStarts[bottomLine])
  628.     {
  629.         // count up the lines to current
  630.         for (    theLine = 0;
  631.                 (**gSrcWind_TE32KH).selStart >= (**gSrcWind_TE32KH).lineStarts[theLine];
  632.                 theLine++)
  633.             ;
  634.         // position back 1/2 screen so selection is in middle of screen
  635.         theLine = theLine - gLineCount / 2;
  636.         if (theLine<0)
  637.             theLine=0;
  638.         SetControlValue(gSrcWind_VScroll, theLine);
  639.         scrollAmt = topLine-theLine;
  640.         TE32KScroll(0L, (long)((long)scrollAmt*(long)(**gSrcWind_TE32KH).lineHeight), gSrcWind_TE32KH);
  641.         AdjustScrollBar();
  642.     }
  643.     return 0; // should be void fn!?
  644. }
  645.  
  646.  
  647.  
  648. // ==============================================
  649. void SelectAllText(void)
  650. {    
  651.     End_Make_Undoable();
  652.     End_Make_Redoable();
  653.     TE32KSetSelect(0, (**gSrcWind_TE32KH).teLength, gSrcWind_TE32KH);
  654.     UpdateWindow(gSrcWind_Window);
  655. }
  656.  
  657.  
  658.  
  659. // ==============================================
  660. int SetView(WindowPtr w)
  661. {
  662.     Rect        TviewRect;
  663.     // calculate viewable area
  664.     TviewRect = w->portRect;
  665.     TviewRect.right  -= SBarWidth;
  666.     TviewRect.bottom -= SBarWidth;
  667.     InsetRect(&TviewRect, 2, 2); // add 2 pixel padding inside window frame
  668.     RectToLongRect(&TviewRect, &(**gSrcWind_TE32KH).viewRect);
  669.  
  670.     gLineCount = ((**gSrcWind_TE32KH).viewRect.bottom-(**gSrcWind_TE32KH).viewRect.top)/(**gSrcWind_TE32KH).lineHeight;
  671.     (**gSrcWind_TE32KH).viewRect.bottom = (**gSrcWind_TE32KH).viewRect.top + (**gSrcWind_TE32KH).lineHeight*gLineCount;
  672.     (**gSrcWind_TE32KH).destRect.right = (**gSrcWind_TE32KH).viewRect.right;
  673.     TE32KCalText(gSrcWind_TE32KH);
  674.     return 0; // should be void fn!?
  675. }
  676.  
  677.  
  678.  
  679. // ==============================================
  680. int UpdateWindow(WindowPtr theWindow)
  681. {
  682.     GrafPtr        savePort;
  683.     LongRect    LviewRect;
  684.     
  685.     GetPort(&savePort);
  686.     SetPort(theWindow);
  687.  
  688.     BeginUpdate(theWindow);
  689.     EraseRect(&theWindow->portRect);
  690.     DrawControls(theWindow);
  691.     DrawGrowIcon(theWindow);
  692.     RectToLongRect(&theWindow->portRect, &LviewRect);
  693.     TE32KUpdate(&LviewRect, gSrcWind_TE32KH);
  694.     EndUpdate(theWindow);
  695.  
  696.     SetPort(savePort);
  697.     return 0; // should be void fn!?
  698. }
  699.  
  700.  
  701. // ==============================================
  702. // So outside can call scrolling without accessing locals
  703. void ScrollEditHome(void)
  704. {
  705.     short    controlMin,controlVal;
  706.     int        scrollAmt;
  707.     
  708.     controlMin = GetControlMinimum(gSrcWind_VScroll);
  709.     controlVal = GetControlValue(gSrcWind_VScroll);
  710.             
  711.     // how far to get back to top?
  712.     scrollAmt = controlVal-controlMin;
  713.     if (scrollAmt>0)
  714.         {
  715.         // set scrollbar to min
  716.         SetControlValue(gSrcWind_VScroll, controlMin);
  717.         TE32KScroll(0L, (long)((long)scrollAmt*(long)(**gSrcWind_TE32KH).lineHeight), gSrcWind_TE32KH);
  718.         AdjustScrollBar();
  719.         }
  720. }
  721.  
  722. // ==============================================
  723. // So outside can call scrolling without accessing locals
  724. void ScrollEditEnd(void)
  725. {
  726.     short    controlMax,controlVal;
  727.     int        scrollAmt;
  728.     
  729.     controlMax = GetControlMaximum(gSrcWind_VScroll);
  730.     controlVal = GetControlValue(gSrcWind_VScroll);
  731.             
  732.     scrollAmt = controlMax-controlVal;
  733.     if (scrollAmt>0)
  734.         {
  735.         SetControlValue(gSrcWind_VScroll, controlMax);
  736.         TE32KScroll(0L, (long)((long)-scrollAmt*(long)(**gSrcWind_TE32KH).lineHeight), gSrcWind_TE32KH);
  737.         AdjustScrollBar();
  738.         }
  739. }
  740.  
  741. // ==============================================
  742. // So outside can call scrolling without accessing locals
  743. void ScrollEditPage(short thePartCode)
  744. {
  745.     ScrollProc(gSrcWind_VScroll, thePartCode);
  746. }
  747.  
  748.  
  749. // ==============================================
  750. static pascal void ScrollProc(ControlHandle theControl, short theCode)
  751. {
  752.     short    controlMax,controlMin,controlVal;
  753.     long    lines;
  754.     int        scrollAmt;
  755.     
  756.     if (theCode == 0)
  757.         return ;
  758.     
  759.     controlMax = GetControlMaximum(theControl);
  760.     controlMin = GetControlMinimum(theControl);
  761.     controlVal = GetControlValue(theControl);
  762.             
  763.     switch (theCode) {
  764.          case kControlUpButtonPart: 
  765.             if (controlVal > controlMin)
  766.                 {
  767.                 SetControlValue(theControl, controlVal-1);
  768.                 TE32KScroll(0L, (long)(**gSrcWind_TE32KH).lineHeight, gSrcWind_TE32KH);
  769.                 }
  770.             break;
  771.         case kControlDownButtonPart: 
  772.             if (controlVal < controlMax)
  773.                 {
  774.                 SetControlValue(theControl, controlVal+1);
  775.                 TE32KScroll(0L, (long)-(**gSrcWind_TE32KH).lineHeight, gSrcWind_TE32KH);
  776.                 }
  777.             break;
  778.         case kControlPageUpPart: 
  779.             if (controlVal > controlMin)
  780.                 {
  781.                 // calculate # of lines in a page (minus one) so we can scroll that far
  782.                 lines = ((*gSrcWind_TE32KH)->viewRect.bottom - (*gSrcWind_TE32KH)->viewRect.top)/(**gSrcWind_TE32KH).lineHeight-1;
  783.                 scrollAmt = (controlVal-lines < controlMin) ? controlVal-controlMin : lines;
  784.                 SetControlValue(theControl,controlVal-scrollAmt);
  785.                 TE32KScroll(0L,(long) ((long)scrollAmt*(long)(**gSrcWind_TE32KH).lineHeight), gSrcWind_TE32KH);
  786.                 }
  787.             break;
  788.         case kControlPageDownPart: 
  789.             if (controlVal < controlMax)
  790.                 {
  791.                 // calculate # of lines in a page (minus one) so we can scroll that far
  792.                 lines = ((**gSrcWind_TE32KH).viewRect.bottom - (**gSrcWind_TE32KH).viewRect.top)/(**gSrcWind_TE32KH).lineHeight-1;
  793.                 scrollAmt = (controlVal+lines > controlMax) ? controlMax-controlVal : lines;
  794.                 SetControlValue(theControl,controlVal+scrollAmt);
  795.                 TE32KScroll(0L, (long)((long)-scrollAmt*(long)(**gSrcWind_TE32KH).lineHeight), gSrcWind_TE32KH);
  796.                 }
  797.             break;
  798.     }
  799.  
  800.     AdjustScrollBar();
  801. }
  802.  
  803.  
  804.  
  805. // ==============================================
  806. int DoContent(WindowPtr theWindow, EventRecord *theEvent)
  807. {
  808.     short            cntlCode;
  809.     ControlHandle     theControl;
  810.     GrafPtr            savePort;
  811.     
  812.     GetPort(&savePort);
  813.     SetPort(theWindow);
  814.  
  815.     GlobalToLocal(&theEvent->where);
  816.     if ((cntlCode = FindControl(theEvent->where, theWindow, &theControl)) == 0)
  817.         {
  818.         // Just a click in text area
  819.         Rect        shortRect;
  820.         LongRect    aLongRect;
  821.         aLongRect = (**gSrcWind_TE32KH).viewRect;
  822.         LongRectToRect(&aLongRect,&shortRect);
  823.  
  824.         if (PtInRect(theEvent->where, &shortRect))
  825.             {
  826.             End_Make_Undoable();
  827.             End_Make_Redoable();
  828.  
  829.             TE32KClick(theEvent->where, (theEvent->modifiers & shiftKey)!=0, gSrcWind_TE32KH);
  830.             }
  831.         }
  832.     else if(cntlCode == kControlIndicatorPart) // was old name: "inThumb"
  833.         {
  834.         // click/drag on the scrollbar thumb
  835.         short oldVal = GetControlValue(theControl);
  836.         TrackControl(theControl,theEvent->where, 0L);
  837.         TE32KScroll(0L,
  838.             (long)((oldVal - (long)GetControlValue(theControl)) * (long)(**gSrcWind_TE32KH).lineHeight),
  839.             gSrcWind_TE32KH);
  840.         }
  841.     else
  842.         {
  843.         // click on other parts of scrollbar
  844.         TrackControl(theControl, theEvent->where, vScrollUPP);
  845.         }
  846.  
  847.     SetPort(savePort);
  848.     return 0; // should be void fn!?
  849. }
  850.  
  851. // ==============================================
  852. // Return selection of TE text in window
  853. long GetSrcWindselStart(void)
  854. {
  855.     return (gSrcWind_TE32KH) ? (**gSrcWind_TE32KH).selStart : 0L;
  856. }
  857.  
  858. // ==============================================
  859. // Return selection of TE text in window
  860. long GetSrcWindselEnd(void)
  861. {
  862.     return (gSrcWind_TE32KH) ? (**gSrcWind_TE32KH).selEnd : 0L;
  863. }
  864.  
  865. // ==============================================
  866. // Return size of TE text in window
  867. long GetSrcWindteLength(void)
  868. {
  869.     return (gSrcWind_TE32KH) ? (**gSrcWind_TE32KH).teLength : 0L;
  870. }
  871.  
  872. // ==============================================
  873. // Return handle to text in window
  874. Handle GetSrcWindhText(void)
  875. {
  876.     return (gSrcWind_TE32KH) ? (**gSrcWind_TE32KH).hText : NULL;
  877. }
  878.  
  879. // ==============================================
  880. // Cut the selection to the clipboard
  881. void SrcWindCutSelToClipboard(void)
  882. {
  883.     Begin_Make_Undoable("Cutting",false);
  884.     ZeroScrap(); // clear out the clipboard
  885.     TE32KCut(gSrcWind_TE32KH);
  886.     TE32KToScrap(); // export
  887.     ShowSelect(); // scroll to cut area
  888.     End_Make_Undoable();
  889. }
  890.  
  891. // ==============================================
  892. // Copy the selection to the clipboard
  893. void SrcWindCopySelToClipboard(void)
  894. {
  895.     Begin_Make_Undoable("Copying",false);
  896.     ZeroScrap(); // clear out the clipboard
  897.     TE32KCopy(gSrcWind_TE32KH);
  898.     TE32KToScrap(); // export
  899.     End_Make_Undoable();
  900. }
  901.  
  902. // ==============================================
  903. // Paste from the clipboard
  904. void SrcWindPasteFromClipboard(void)
  905. {
  906.     Begin_Make_Undoable("Pasting",false);
  907.     TE32KFromScrap(); // import
  908.     TE32KPaste(gSrcWind_TE32KH);
  909.     ShowSelect(); // scroll to pasted area
  910.     End_Make_Undoable();
  911. }
  912.  
  913. // ==============================================
  914. void SrcWindClearSel(void)
  915. {    
  916.     Begin_Make_Undoable("Clearing",false);
  917.     // delete it
  918.     TE32KDelete(gSrcWind_TE32KH);
  919.     End_Make_Undoable();
  920. }
  921.  
  922. // ==============================================
  923. void SrcWindSetSelect(long selStart, long selEnd)
  924. {    
  925.     TE32KSetSelect(selStart, selEnd, gSrcWind_TE32KH);
  926. }
  927.  
  928. // ==============================================
  929. void SrcWindDeleteAllText(void)
  930. {    
  931.     // select everything
  932.     SrcWindSetSelect(0, -1);
  933.     // delete it
  934.     SrcWindClearSel();
  935. }
  936.  
  937. // ==============================================
  938. void SrcWindTEKey(char theKey)
  939. {    
  940.     Begin_Make_Undoable("Typing",true);
  941.     TE32KKey(theKey, gSrcWind_TE32KH);
  942.     End_Make_Undoable();
  943. }
  944.  
  945. // ==============================================
  946. void SrcWindTEDeleteLeftCharKey(void)
  947. {    
  948.     SrcWindSetSelect(GetSrcWindselStart() - 1, GetSrcWindselStart());
  949.     Begin_Make_Undoable("Backspaces",true);
  950.     TE32KDelete(gSrcWind_TE32KH);
  951.     End_Make_Undoable();
  952. }
  953.  
  954. // ==============================================
  955. void SrcWindTEDeleteRightCharKey(void)
  956. {    
  957.     SrcWindSetSelect(GetSrcWindselStart(), GetSrcWindselStart() + 1);
  958.     Begin_Make_Undoable("Deletes",true);
  959.     TE32KDelete(gSrcWind_TE32KH);
  960.     End_Make_Undoable();
  961. }
  962.  
  963. // ==============================================
  964. // Insert a chunk of text into the current selection in source window
  965. void DoSrcWindTextInsert(char * someTextPtr, long someTextSize)
  966. {
  967.     Begin_Make_Undoable("Inserting",false);
  968.     // Delete any selected text before the insertion
  969.     TE32KDelete(gSrcWind_TE32KH);
  970.     // stick in the text
  971.     TE32KInsert(someTextPtr, someTextSize, gSrcWind_TE32KH);
  972.     End_Make_Undoable();
  973. }
  974.  
  975. // ==============================================
  976. // Move the source window's selection to the line # passed
  977. void GotoSrcWindLine(short line_to_go)
  978. {
  979.     short        i;
  980.     long        line_counter = 1,
  981.                 mySelStart = -1,
  982.                 mySelEnd = -1;
  983.     Boolean        foundStart = false;
  984.     long        theMaxLength;
  985.     char        *myptr;
  986.  
  987.     End_Make_Undoable();
  988.     End_Make_Redoable();
  989.  
  990.     /* (Line 1 is a special case, of course!) */
  991.     if (line_to_go <= 1)
  992.     {
  993.         mySelStart = 0;
  994.         foundStart = true;
  995.     }
  996.  
  997.     /* Find start and end of line */
  998.     theMaxLength = (**gSrcWind_TE32KH).teLength-1;
  999.     myptr = *(**gSrcWind_TE32KH).hText;
  1000.     for (i = 0; i < theMaxLength; i++)
  1001.         if (myptr[i] == 0x0d) // new line (Mac CR)?
  1002.             if (!foundStart)
  1003.             {    /* still looking for start of the line */
  1004.                 line_counter += 1;
  1005.                 if (line_counter == line_to_go)
  1006.                 {
  1007.                     mySelStart = i + 1;
  1008.                     foundStart = true;
  1009.                 }
  1010.             }
  1011.             else
  1012.             {    /* now we found the end of the line */
  1013.                 mySelEnd = i + 1;
  1014.                 break;
  1015.             }
  1016.  
  1017.     /* Beep if we found no start of line */
  1018.     if ((mySelStart < 0) && (line_to_go > 1))
  1019.     {    /* Hmm, didn't find it! */
  1020.         mySelStart = theMaxLength;
  1021.         mySelEnd = theMaxLength;
  1022.         SysBeep(1);
  1023.     }
  1024.  
  1025.     /* if no end of line found, ASSUME it is last line of file  */
  1026.     if (mySelEnd < mySelStart)
  1027.         mySelEnd = theMaxLength;
  1028.  
  1029.     /* Set up TE with selection */
  1030.     (**gSrcWind_TE32KH).selStart = mySelStart;
  1031.     (**gSrcWind_TE32KH).selEnd = mySelEnd;
  1032.  
  1033.     /* show them that we're not in Kansas anymore! */
  1034.     SetPort(gSrcWind_Window);
  1035.     InvalRect(&(gSrcWind_Window->portRect));
  1036.     ShowSelect();
  1037. }
  1038.  
  1039.  
  1040. // ==============================================
  1041. // Search forward/backward from current start of selection, to match braces.
  1042. // This is a quick hack, it currently does *not* handle skipping over braces in
  1043. // comments or quoted strings, so beware.
  1044. void MatchBracesAtCurSel(void)
  1045. {
  1046.     int        valence;        // keep track of brace level
  1047.     long    theMaxLength;    // remember end index of buffer
  1048.     long    begPos, endPos;    // forward/backward search indexes
  1049.     char    *textPtr;        // simplified pointer to text buffer
  1050.  
  1051.     End_Make_Undoable();
  1052.     End_Make_Redoable();
  1053.  
  1054.     // find end of buffer
  1055.     theMaxLength = (**gSrcWind_TE32KH).teLength;
  1056.     // start out at the beginning of the selection
  1057.     begPos = (**gSrcWind_TE32KH).selStart;
  1058.     textPtr = (*(**gSrcWind_TE32KH).hText);
  1059.  
  1060.     // If we are sitting right before (on) a close brace, back up one so that
  1061.     // we don't immediately count it when scanning backwards.
  1062.     if ((textPtr[begPos] == '}') && (begPos>0))
  1063.         begPos--;
  1064.  
  1065.     // search backward for first open brace we find (almost).  We have to
  1066.     // remember valence in case there's an intermediate { } to skip over.
  1067.     valence = 0;
  1068.     while ((begPos>=0) && (valence>=0))
  1069.         {
  1070.         if (textPtr[begPos] == '{')
  1071.             valence--;    // back out a level
  1072.         else if (textPtr[begPos] == '}')
  1073.             valence++;    // in a level
  1074.         if (valence>=0)
  1075.             begPos--; // keep going back...
  1076.         }
  1077.  
  1078.     // At this point we should have found a start brace, and the valence is -1.
  1079.     // If this is not true, we could search forward for the first open brace
  1080.     // and start from there instead, but that's not the best assumption, IMHO.
  1081.     // For this implementation, we simply decide it is an error & stop.
  1082.     if (valence < 0)
  1083.         {
  1084.         // begPos is ON the open brace... we want to start searching forward
  1085.         // one character AFTER this.
  1086.         endPos = begPos+1;
  1087.  
  1088.         // search forward for first close brace we find (almost).  We have to
  1089.         // remember valence in case there's an intermediate { } to skip over.
  1090.         valence = 0;
  1091.         while ((endPos<theMaxLength) && (valence>=0))
  1092.             {
  1093.             if (textPtr[endPos] == '{')
  1094.                 valence++;    // in a level
  1095.             else if (textPtr[endPos] == '}')
  1096.                 valence--;    // back out level
  1097.             // increase ALWAYS, this lets us select end brace too
  1098.             endPos++; // keep going on...
  1099.             }
  1100.         }
  1101.  
  1102.     // OK, if we've gotten this far and valence is negative, we found both ends.
  1103.     // Otherwise no matches were found, and we beep!
  1104.     if (valence < 0)
  1105.         {
  1106.         // select what we found
  1107.         (**gSrcWind_TE32KH).selStart = begPos;
  1108.         (**gSrcWind_TE32KH).selEnd   = endPos;
  1109.  
  1110.         // show selected area
  1111.         SetPort(gSrcWind_Window);
  1112.         InvalRect(&(gSrcWind_Window->portRect));
  1113.         ShowSelect();
  1114.         }
  1115.     else
  1116.         SysBeep(1);
  1117.  
  1118. }
  1119.  
  1120.  
  1121.  
  1122. // ==============================================
  1123. void MyResizeWindow(WindowPtr w, short h, short v)
  1124. {
  1125.     Rect    oldHorizBar;
  1126.     Rect     r;
  1127.     
  1128.     SetPort(w);
  1129.  
  1130.     oldHorizBar = w->portRect;
  1131.     oldHorizBar.top = oldHorizBar.bottom - (SBarWidth+1);
  1132.  
  1133.     SizeWindow(w, h, v, false);
  1134.  
  1135.     // remember this new size in prefs
  1136.     GetGlobalWindowRect(w, &(**gFilePrefs_h).srcWind_pos);
  1137.  
  1138.     InvalRect(&w->portRect);
  1139.     
  1140.     SetView(w);
  1141.  
  1142.     EraseRect(&oldHorizBar);
  1143.     
  1144.     MoveControl(gSrcWind_VScroll, w->portRect.right - SBarWidth, w->portRect.top-1);
  1145.     SizeControl(gSrcWind_VScroll, SBarWidth+1, w->portRect.bottom - w->portRect.top-(SBarWidth-2));
  1146.     r = (**gSrcWind_VScroll).contrlRect;
  1147.     ValidRect(&r);
  1148.  
  1149.     AdjustScrollBar();    
  1150. } // MyResizeWindow
  1151.  
  1152.  
  1153.  
  1154. // ==============================================
  1155. static void MyGrowWindow(WindowPtr w, Point p)
  1156. {
  1157.     GrafPtr        savePort;
  1158.     long        theResult;
  1159.     Rect        r;
  1160.     
  1161.     GetPort(&savePort);
  1162.     SetPort(w);
  1163.  
  1164.     GetMaxGrowRect(w, &r);    
  1165.     theResult = GrowWindow(w, p, &r);
  1166.     if (theResult != 0)
  1167.         MyResizeWindow(w, LoWord(theResult), HiWord(theResult));
  1168.  
  1169.     SetPort(savePort);
  1170. } // MyGrowWindow
  1171.  
  1172.  
  1173.  
  1174. // ==============================================
  1175. int CloseMyWindow(void)
  1176. {
  1177.  
  1178.     if (gSrcWind_VRefNum != 0)
  1179.     {
  1180.         FilePrefs_Write(gSrcWind_VRefNum, gSrcWind_FileName);    // Save window info
  1181.         // OK, now we're done with this file, release the pesky Working Directory
  1182. //        CloseWD(gSrcWind_VRefNum);
  1183.     }
  1184.  
  1185.     // if there's a window (always) then hide it
  1186.     if (gSrcWind_Window)
  1187.         HideWindow(gSrcWind_Window);
  1188.     gSrcWind_visible = false;
  1189.     ShowArrowCursor();
  1190.  
  1191.     // Image window also no longer valid!
  1192.     CloseImageWindow();
  1193.     gImageWindIsValid = false;
  1194.  
  1195.     // get rid of TE text (select all & delete)
  1196.     if (gSrcWind_TE32KH)
  1197.     {
  1198.         TE32KSetSelect(0, (**gSrcWind_TE32KH).teLength, gSrcWind_TE32KH);
  1199.         TE32KDelete(gSrcWind_TE32KH);
  1200.     }
  1201.  
  1202.     AdjustScrollBar();
  1203.  
  1204.     SetUpFiles();
  1205.  
  1206.     return 0; // should be void fn!?
  1207. }
  1208.  
  1209.  
  1210. // ==============================================
  1211. int    DoActivateEditor(Boolean becomingActive)
  1212. {
  1213.     if (becomingActive)
  1214.     {
  1215.         TE32KActivate(gSrcWind_TE32KH);
  1216.         ShowControl(gSrcWind_VScroll);
  1217.         DrawGrowIcon(gSrcWind_Window);
  1218.     }
  1219.     else
  1220.     {
  1221.         TE32KDeactivate(gSrcWind_TE32KH);
  1222.         HideControl(gSrcWind_VScroll);
  1223.         /* the growbox should be changed immediately here */
  1224.         DrawGrowIcon(gSrcWind_Window);
  1225.     }
  1226.     return 0; // should be void fn!?
  1227. }
  1228.  
  1229. // ==============================================
  1230. void Init_Editor(void) 
  1231. {
  1232.     CursHandle    hCurs;
  1233.     TE32KInit();
  1234.     vScrollUPP = NewControlActionProc(ScrollProc);
  1235.     // Note: iBeamCursor & watchCursor are defined in ToolUtils.h
  1236.     hCurs = GetCursor(iBeamCursor);
  1237.     gEditCursor = **hCurs;
  1238.     gSrcWind_Window = NULL;
  1239.     SetUpFiles();
  1240.     PreInitWindows();
  1241. }
  1242.  
  1243.  
  1244. // ==============================================
  1245. int DoEditMouseDown(int windowPart, WindowPtr whichWindow, EventRecord *myEvent)
  1246. {
  1247.     switch (windowPart) {
  1248.         case inGoAway:
  1249.             if (ours(whichWindow) && (gDoingRender == 0))
  1250.                 if (TrackGoAway(gSrcWind_Window, myEvent->where))
  1251.                     DoFile(fmn_close);
  1252.             break;
  1253.  
  1254.         case inDrag:
  1255.             if (ours(whichWindow))
  1256.             {
  1257.                 SelectWindow(whichWindow);
  1258.                 DragWindow(whichWindow, myEvent->where, &gDragBounds);
  1259.                 GetGlobalWindowRect(whichWindow, &(**gFilePrefs_h).srcWind_pos);
  1260.             }
  1261.             break;
  1262.  
  1263.         case inGrow:
  1264.             if (ours(whichWindow))
  1265.                 MyGrowWindow(whichWindow, myEvent->where);
  1266.             break;
  1267.  
  1268.         case inZoomIn:
  1269.         case inZoomOut:
  1270.             SelectWindow(whichWindow);
  1271.             if (TrackBox(whichWindow, myEvent->where, windowPart))
  1272.             {
  1273.                 EraseRect(&((WindowPtr)whichWindow)->portRect);
  1274.                 ZoomWindow((WindowPtr)whichWindow, windowPart, (WindowPtr)whichWindow==FrontWindow());
  1275.                 MyResizeWindow(whichWindow,
  1276.                         whichWindow->portRect.right - whichWindow->portRect.left,
  1277.                         whichWindow->portRect.bottom - whichWindow->portRect.top);
  1278.             }
  1279.             break;
  1280.  
  1281.         case inContent:
  1282.             if (whichWindow != FrontWindow())
  1283.                 SelectWindow(whichWindow);
  1284.             else if (ours(whichWindow))
  1285.                 DoContent(whichWindow, myEvent);
  1286.             break;
  1287.     }
  1288.     return 0; // should be void fn!?
  1289. }
  1290.  
  1291.  
  1292.  
  1293. // ==============================================
  1294. void SrcWindMaintainCursor(void)
  1295. {
  1296.     Point        pt;
  1297.     WindowPeek    wPtr;
  1298.     GrafPtr        savePort;
  1299.     Rect        shortRect;
  1300.     LongRect    aLongRect;
  1301.     
  1302.     GetPort(&savePort);
  1303.  
  1304.     // update the cursor if over our window
  1305.     wPtr=(WindowPeek)FrontWindow();
  1306.     if ( ours((WindowPtr)wPtr) )
  1307.     {
  1308.         SetPort((GrafPtr)wPtr);
  1309.         // is cursor inside editor window?
  1310.         GetMouse(&pt);
  1311.         aLongRect = (**gSrcWind_TE32KH).viewRect;
  1312.         LongRectToRect(&aLongRect,&shortRect);
  1313.         if (PtInRect(pt, &shortRect))
  1314.             SetCursor(&gEditCursor);
  1315.         else
  1316.             ShowArrowCursor();
  1317.     }
  1318.     // let cursor blink
  1319.     if (gSrcWind_TE32KH)
  1320.         TE32KIdle(gSrcWind_TE32KH);
  1321.  
  1322.     SetPort(savePort);
  1323. }
  1324.  
  1325.  
  1326. static void SrcWindClickLoop(void)
  1327. {
  1328.     SrcWindClickRoutine();
  1329. }
  1330.  
  1331.  
  1332. static void SrcWindClickRoutine(void)
  1333. {
  1334.     short        controlMax,controlMin,controlVal,lineHeight;
  1335.     LongRect    aLongRect;
  1336.     Rect        viewRect;
  1337.     Point        mousePosShort;
  1338.     RgnHandle    saveClip;
  1339.     long        vDelta;
  1340.  
  1341.     aLongRect = (**gSrcWind_TE32KH).viewRect;
  1342.     LongRectToRect(&aLongRect,&viewRect);
  1343.     lineHeight = (**gSrcWind_TE32KH).lineHeight;
  1344.  
  1345.     vDelta = 0L;
  1346.     
  1347.     GetMouse(&mousePosShort);
  1348.     
  1349.     if (!PtInRect(mousePosShort,&viewRect))
  1350.     {
  1351.         controlMax = GetControlMaximum(gSrcWind_VScroll);
  1352.         controlMin = GetControlMinimum(gSrcWind_VScroll);
  1353.         controlVal = GetControlValue(gSrcWind_VScroll);
  1354.         
  1355.         if (mousePosShort.v>viewRect.bottom && controlVal<controlMax)
  1356.         {
  1357.             vDelta = -lineHeight;
  1358.             SetControlValue(gSrcWind_VScroll,controlVal+1);
  1359.         }
  1360.         
  1361.         else if (mousePosShort.v<viewRect.top && controlVal>controlMin)
  1362.         {
  1363.             vDelta = lineHeight;
  1364.             SetControlValue(gSrcWind_VScroll,controlVal-1);
  1365.         }
  1366.         
  1367.     }
  1368.     
  1369.     if (vDelta)
  1370.     {
  1371.         saveClip = NewRgn();
  1372.         GetClip(saveClip);
  1373.         ClipRect(&(gSrcWind_Window->portRect));
  1374.         
  1375.         TE32KScroll(0,vDelta,gSrcWind_TE32KH);
  1376.         
  1377.         SetClip(saveClip);
  1378.         DisposeRgn(saveClip);
  1379.     }
  1380. }
  1381.  
  1382. // ==============================================
  1383. // UNDO / REDO interface functions
  1384. // (called in Pov.c and UndoRedoSystem.c)
  1385. // ==============================================
  1386.  
  1387. // ==============================================
  1388. // Undo function
  1389. void SrcWindUndo(void)
  1390. {
  1391.     if(My_DoUndo() == true)
  1392.         gSrcWind_dirty = true;
  1393. //    else
  1394. //        => error, can't undo
  1395.     ShowSelect(); // scroll to undone area
  1396. }
  1397.  
  1398. // ==============================================
  1399. // Redo function
  1400. void SrcWindRedo(void)
  1401. {
  1402.     if(My_DoRedo() == true)
  1403.         gSrcWind_dirty = true;
  1404. //    else
  1405. //        => error, can't redo
  1406.  
  1407.     ShowSelect(); // scroll to redone area
  1408. }
  1409.